﻿namespace Jhong.Data.SQLServer
{
    using Jhong.Data.Core.Common;
    using System;
    using System.Data;
    using System.Data.Common;
    using System.Data.SqlClient;
    using System.Linq;

    public class SQLServerContext : DBContext
    {
        public SQLServerContext(SqlConnection conn)
            : base(conn)
        {
        }

        public SQLServerContext(string connectionString)
            : this(new SqlConnection(connectionString))
        {
        }

        public override IDbCommand GetDBCommand(string sqlStr, DbParameter[] parameters)
        {
            SqlCommand cmd;
            if (null != this.Translation) cmd = new SqlCommand(sqlStr, this.Connection as SqlConnection, this.Translation as SqlTransaction);
            else cmd = new SqlCommand(sqlStr, this.Connection as SqlConnection);
            if (null != parameters && parameters.Count() > 0) cmd.Parameters.AddRange(parameters);
            return cmd;
        }

        public override int[] Execute()
        {
            var count = this._execList.Count();
            var result = new int[count];
            for (int i = 0; i < count; i++)
            {
                var currExec = this._execList[i];
                result[i] = this.GetDBCommand(currExec.Item1, currExec.Item2).ExecuteNonQuery();
            }
            this.ClearExexList();
            return result;
        }

        private DataTable FillData(SqlCommand cmd)
        {
            var adt = new SqlDataAdapter(cmd);
            var dt = new DataTable();
            adt.Fill(dt);
            adt.Dispose();
            return dt;
        }

        public override DataTable[] QueryToDataTables()
        {
            var count = this._execList.Count();
            var dts = new DataTable[count];
            for (int i = 0; i < count; i++)
            {
                var currExec = this._execList[i];
                var cmd = this.GetDBCommand(currExec.Item1, currExec.Item2) as SqlCommand;
                dts[i] = this.FillData(cmd);
            }
            this.ClearExexList();
            return dts;
        }

        protected override DbParameter GetDBParameter(string parameterName, object value)
        {
            var parameter = new SqlParameter();
            parameter.ParameterName = "@" + parameterName;
            switch (Type.GetTypeCode(value.GetType()))
            {
                case TypeCode.Boolean:
                    parameter.SqlDbType = SqlDbType.Bit;
                    break;

                case TypeCode.Byte:
                    parameter.SqlDbType = SqlDbType.TinyInt;
                    break;

                case TypeCode.Char:
                    parameter.SqlDbType = SqlDbType.Char;
                    break;

                case TypeCode.DateTime:
                    parameter.SqlDbType = SqlDbType.DateTime;
                    break;

                case TypeCode.Decimal:
                    parameter.SqlDbType = SqlDbType.Decimal;
                    break;

                case TypeCode.Double:
                    parameter.SqlDbType = SqlDbType.Float;
                    break;

                case TypeCode.Int16:
                    parameter.SqlDbType = SqlDbType.SmallInt;
                    break;

                case TypeCode.Int32:
                    parameter.SqlDbType = SqlDbType.Int;
                    break;

                case TypeCode.Int64:
                    parameter.SqlDbType = SqlDbType.BigInt;
                    break;

                case TypeCode.Object:
                    parameter.SqlDbType = SqlDbType.Binary;
                    break;

                case TypeCode.SByte:
                    parameter.SqlDbType = SqlDbType.TinyInt;
                    break;

                case TypeCode.Single:
                    parameter.SqlDbType = SqlDbType.Float;
                    break;

                case TypeCode.String:
                    parameter.SqlDbType = SqlDbType.VarChar;
                    break;

                case TypeCode.UInt16:
                    parameter.SqlDbType = SqlDbType.SmallInt;
                    break;

                case TypeCode.UInt32:
                    parameter.SqlDbType = SqlDbType.Int;
                    break;

                case TypeCode.UInt64:
                    parameter.SqlDbType = SqlDbType.BigInt;
                    break;

                default:
                    throw new Exception("不支持该类型");
            }
            parameter.Value = value;
            return parameter;
        }
    }
}